#******************************************************************************
#
#              Copyright (c) 2009 Sony Pictures Imageworks Inc.
#                             All rights reserved.
#
#   This  material  contains  the confidential and  proprietary information
#   of Sony Pictures Imageworks Inc.   and may not be disclosed,  copied or
#   duplicated  in any form,  electronic or hardcopy,  in whole  or in part,
#   without  the express prior written  consent of Sony Pictures Imageworks
#   Inc. This copyright notice does not imply publication.
#
#******************************************************************************

__all__ =  ["buildRenderCommand"]

import os, logging
log = logging.getLogger('ArnoldRenderUtils')

from Katana import Nodes2DAPI, Nodes3DAPI, RenderingAPI

from Nodes3DAPI import Rendering
from Nodes3DAPI import RenderingUtil

def buildRenderCommand(producer, renderSettings, nodeName, renderTime,
    mainSequenceId, sequenceIDMap, useID, commonChildEnv):
    
    # Check for external listener
    externalListenerInfo = Nodes2DAPI.GetExternalRenderListenerInfo()
    if externalListenerInfo is None:
        raise RuntimeError, "External render listener is not active."

    if os.environ.get('ARNOLD_VERSION', '').startswith('2.'):
        raise RuntimeError, "This version of Katana requires Arnold 3 or higher."

    # Write support files
    tmpProductStateTableFilename = Rendering.writeProductStateTable(RenderingUtil.GetTmpLocalFile)
    tmpProducerTextFilename = Rendering.writeProducerText(RenderingUtil.GetTmpLocalFile, producer)

    Rendering.global_tmp_filenames[mainSequenceId] = (tmpProductStateTableFilename,
                                                      tmpProducerTextFilename)
    
    interactiveOutputsList = []
    interactiveOutputs = Nodes3DAPI.GetInteractiveOutputs(producer)
    
    if interactiveOutputs:
        for outputName in interactiveOutputs:
            channel = _getChannelName(producer, outputName)
            try:
                sequenceId = sequenceIDMap[outputName]
                #interactiveOutputsList.append((outputName, sequenceId, channel))
                interactiveOutputsList.append((outputName, sequenceId, channel))
            except Exception:
                errorMessage = "sequenceId for output '%s' not found in map" % outputName
                raise RuntimeError, errorMessage
    else:
        interactiveOutputsList.append(('primary', mainSequenceId, _getChannelName(producer, 'primary')))
    
    windowOrigin, originalSize, cropWindow, screenWindow, dataWindow = \
        Rendering.coordinateNoodling(renderSettings)

    modifyChildEnv = {}

    arnoldPythonPath = os.environ.get('KATANA_PYTHON_LIBS', '')
    if 'PYTHONPATH' in os.environ:
        if arnoldPythonPath: arnoldPythonPath += ':'
        arnoldPythonPath += os.environ['PYTHONPATH']
    modifyChildEnv['PYTHONPATH'] = arnoldPythonPath

    arnoldSpImportPackages = os.environ.get('KATANA_SPIMPORT_PACKAGES', '')
    if 'SPIMPORT_PACKAGES' in os.environ:
        if arnoldSpImportPackages: arnoldSpImportPackages += ':'
        arnoldSpImportPackages += os.environ['SPIMPORT_PACKAGES']
    modifyChildEnv['SPIMPORT_PACKAGES'] = arnoldSpImportPackages
    modifyChildEnv['SPIMPORT_NOWARNING'] = '1'
    
    # add ARNOLD_LD_LIBRARY_PATH into LD_LIBRARY_PATH
    libPath = os.environ.get('LD_LIBRARY_PATH', '')
    arnoldLibPath = os.environ.get('ARNOLD_LD_LIBRARY_PATH')
    if arnoldLibPath:
        modifyChildEnv['LD_LIBRARY_PATH'] = arnoldLibPath + ':' + libPath  + ':' + RenderingAPI.RenderPlugins.GetRendererPluginBinDir("arnold")
    
    # for debug purposes, we sometimes need to overload existing library
    arnoldPreload = os.environ.get('LD_PRELOAD', '')
    if 'ARNOLD_LD_PRELOAD' in os.environ:
       if arnoldPreload: arnoldPreload += ':'
       arnoldPreload += os.environ['ARNOLD_LD_PRELOAD']
    modifyChildEnv['LD_PRELOAD'] = arnoldPreload

    # Build command line
    cmd = ''

    if modifyChildEnv or commonChildEnv:
        cmd = 'env '
        for key, value in modifyChildEnv.iteritems():
            cmd += '%s=%s ' % (key,value)
        for key, value in commonChildEnv.iteritems():
            cmd += '%s=%s ' % (key,value)
            
            
    # Get the arnold executable
    pluginPath = RenderingAPI.RenderPlugins.GetRendererPluginBinDir("arnold")
    arnoldRender = os.path.join(pluginPath, "arnold_render")

    cmd += arnoldRender
    cmd += ' --producerText %s' % tmpProducerTextFilename
    cmd += ' --productStateTable %s' % tmpProductStateTableFilename
    cmd += ' --outputAddress %s' % externalListenerInfo[0]
    cmd += ' --width %d' % (dataWindow[2]-dataWindow[0])
    cmd += ' --height %d' % (dataWindow[3]-dataWindow[1])
    cmd += ' --cropWindow %f,%f,%f,%f' % cropWindow
    cmd += ' --screenWindow %f,%f,%f,%f' % screenWindow
    cmd += ' --frameTime %f' % renderTime
    cmd += ' --frameName %s' % nodeName
    cmd += ' --frameOrigin %d,%d' % windowOrigin
    cmd += ' --displayWindowSize %d,%d' % originalSize    
    if useID:
        cmd += ' --generateIDs'

    for interactiveOutput in interactiveOutputsList:
        cmd += ' --outputChannel %s' % interactiveOutput[2]
        cmd += ' --frameID %d' % interactiveOutput[1]
                             

    # derive app_log info
    appVersion = os.environ.get('ARNOLD_VERSION', 'unknown')
    appPath = arnoldRender

    return cmd, appVersion, appPath

def _getChannelName(producer, outputName):
    channelAttr = producer.getDelimitedLocalAttribute("renderSettings.outputs.%s.rendererSettings.channel" % outputName)
    if channelAttr:
        channel = channelAttr.getData()[0]
    else:
        channel = 'RGBA'

    return channel
